﻿using System;
using System.Collections.Generic;

namespace JTLeigh.Commerce.Spencer.Core.Common.Entities
{

    /// <summary>
    /// Represents a fully-qualified reference to a product in a catalog.
    /// </summary>
    /// <remarks>
    /// <para>
    /// <see cref="CatalogProductReference"/> can be used as the key for a <see cref="Dictionary{TKey,TValue}"/>
    /// when you want to organize data by product, but need to support multiple catalogs.
    /// </para>
    /// </remarks>
    public class CatalogProductReference
    {

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="CatalogProductReference"/> class with the
        /// specified catalog identifier and product identifier.
        /// </summary>
        /// <param name="catalogId">The catalog identifier.</param>
        /// <param name="productId">The product identifier.</param>
        public CatalogProductReference(string catalogId, string productId)
        {
            Safety.AssertArgumentNotNull("catalogId", catalogId);
            Safety.AssertArgumentNotNull("productId", productId);

            CatalogId = catalogId;
            ProductId = productId;
        }
        #endregion // Constructors

        #region Properties

        /// <summary>
        /// Gets the catalog identifier.
        /// </summary>
        /// <value>A catalog identifier <see cref="String"/>.</value>
        public string CatalogId { get; private set; }

        /// <summary>
        /// Gets the product identifier.
        /// </summary>
        /// <value>A product identifier <see cref="String"/>.</value>
        public string ProductId { get; private set; }

        #endregion // Properties

        #region Methods

        /// <summary>
        /// Compares this object and the specified object for equality.
        /// </summary>
        /// <param name="obj">The <see cref="object"/> to compare.</param>
        /// <returns><see langword="true"/> if the two objects are equal, <see langword="false"/>
        /// otherwise.</returns>
        /// <remarks>
        /// <para>
        /// The two objects will be equal if both are <see cref="CatalogProductReference"/> and if
        /// both their <see cref="CatalogProductReference.CatalogId"/> and <see cref="CatalogProductReference.ProductId"/>
        /// properties are equal.
        /// </para>
        /// </remarks>
        public override bool Equals(object obj)
        {
            CatalogProductReference product;

            if (obj == null)
            {
                return false;
            }

            if (obj == this)
            {
                return true;
            }

            product = obj as CatalogProductReference;
            if (product == null)
            {
                return false;
            }

            if (!CatalogId.Equals(product.CatalogId))
            {
                return false;
            }

            if (!ProductId.Equals(product.ProductId))
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// Gets the hash code for this object.
        /// </summary>
        /// <returns>The hash code.</returns>
        public override int GetHashCode()
        {
            int hashCode;

            hashCode = 0;
            hashCode = (hashCode * 397) ^ CatalogId.GetHashCode();
            hashCode = (hashCode * 397) ^ ProductId.GetHashCode();

            return hashCode;
        }

        #endregion // Methods

    }

}
